#ifndef ODBC_DETAILS_STRING_BUFFER_BASE_HPP
#define ODBC_DETAILS_STRING_BUFFER_BASE_HPP

#include "odbc/details/buffer_base.hpp"
#include <string>
#include <vector>
#include <algorithm>

namespace odbc { namespace details
{

/// \ingroup odbcpp
/// \brief It implements the common functionality needed by a buffer that maps a string.
/// \param Tr the traits used for character comparison, needed by std::basic_string type.
/// \param Alloc the allocator used by std::basic_string type.
template< class Tr = std::char_traits< char>, class Alloc = std::allocator< char> >
class string_buffer_base: public buffer_base< odbc_types::odbc_char, sql_types::sql_char>
{
	typedef buffer_base< odbc_types::odbc_char, sql_types::sql_char> MyBaseT_;
public:
	typedef std::basic_string< char, Tr, Alloc> value_type;
	typedef std::vector< char> buffer_type;

public:
	/// \brief It initializes a buffer of the specified size.
	/// \param size the size of the memory to be allocated for the buffer.
	string_buffer_base( size_type size = 256)
		: MyBaseT_( size)
		, buffer_( size)
	{
	}

	/// \brief It initializes the buffer with the specified size, holding the given initial value.
	/// \param initial_value the value to initialize the buffer with.
	/// \param size the size of the buffer.
	/// \note If the size of the buffer is less than the value to be used for initialization, the value is truncated.
	string_buffer_base( const value_type& initial_value, size_type size)
		: MyBaseT_( size)
		, buffer_( size)
	{
		this->set_value( initial_value);
	}

	/// \brief It sets the specified value to the buffer.
	/// \note If the size of the buffer is less than the value to be used for initialization, the value is truncated.
	void set_value( const value_type& value)
	{
		typename value_type::const_iterator b = value.begin(), e = b;
		std::advance( e, std::min( value.size(), buffer_.size()));
		std::copy( b, e, buffer_.begin());

		this->set_length_indicator( buffer_.size());
	}

	/// \brief It gets the value from the buffer.
	/// \pre The buffer doesn't contain a NULL value.
	value_type value() const { return std::string( &buffer_.front()); }

	/// \brief It gets the memory address of the buffer.
	/// \details
	///		The buffer address is requested by ODBC API functions and it is not intended for direct use.
	/// \{
	void* buffer_addr() { return static_cast< void*>( &buffer_); }
	const void* buffer_addr() const { return static_cast<const void*>( &buffer_); }
	/// \}

	/// \brief It gets the size of the buffer.
	size_type size() const { return sizeof( buffer_); }


private:
	buffer_type buffer_;
};


} } // namespace details // namespace odbc

#endif // ODBC_DETAILS_STRING_BUFFER_BASE_HPP
